#include "text.h"

#include "SDL.h"
#include "SDL_ttf.h"

#include "global.h"
#include "data.h"
#include "palette.h"

// font used on the game
TTF_Font *font_error = NULL, 
	 *antiqua8 = NULL,
	 *antiqua16 = NULL,
	 *antiqua32 = NULL,
	 *alphbeta8 = NULL,
	 *kyrou8 = NULL,
	 *editundo14 = NULL,
	 *pixChicago8 = NULL,
	 *pixChicago16 = NULL;

// Load all necessary fonts for the game.
void load_fonts()
{
	static struct
	{
		TTF_Font** font;
		char* filename;
		int size;
	} font[] = {
		{ &alphbeta8, "alphbeta.ttf", 13 },
		{ &antiqua8, "PixAntiqua.ttf", 8 },
		{ &antiqua16, "PixAntiqua.ttf", 16 },
		{ &antiqua32, "PixAntiqua.ttf", 32 },
		{ &kyrou8, "Kyrou.ttf", 8 },
		{ &editundo14, "editundo.ttf", 14 },
		{ &pixChicago8, "pixChicago.ttf", 8 },
		{ &pixChicago16, "pixChicago.ttf", 16 },
		{ NULL, NULL, 0 }
	};

	int i = 0;

	while(font[i].filename)
	{
		TTF_Font* ft = TTF_OpenFont(datapath(font[i].filename), 
				font[i].size);
		if(!ft)
			ui_error(_("Could not load font %s: %s"), 
					font[i].filename, TTF_GetError());
		**(&font[i].font) = ft;

		i++;
	}
}


// Write text on the screen. Returns the y position of the next line.
int writef(Pencil pencil, int x, int y, char* fmt, ...)
{
	if(!pencil.sf)
		ui_error(_("Invalid surface."));
	if(!pencil.font)
		ui_error(_("Invalid font."));

	// create print string
	char buffer[1024];
	va_list args;
	va_start(args, fmt);
	vsnprintf(buffer, 1024, fmt, args);
	va_end(args);

	// display on the screen
	SDL_Surface* text = TTF_RenderUTF8_Solid(pencil.font, buffer, 
			pencil.color);
	if(!text)
		ui_error(_("Error drawing text: %s"), TTF_GetError());

	SDL_BlitSurface(text, NULL, pencil.sf, &(SDL_Rect){x,y});
	SDL_FreeSurface(text);

	return y + TTF_FontLineSkip(pencil.font);
}


static int wordwrap(char* text, int n_chars, char** lines)
{
	int ln = 0, i = 0, cl = 0;
	lines[0] = text;
	
	if(n_chars == 0)
		return 1;

	while(text[i] != '\0')
	{
		if(cl >= n_chars)
		{
			while(text[i--] != ' ');
			lines[++ln] = &text[i+2];
			text[i+1] = '\0';
			cl = 0;
			i++;
		}
		i++;
		cl++;
	}

	return ln+1;
}


// Create a image with the text specified. The text will be shadowed.
// The surface must be cleaned afterwards.
SDL_Surface* dbl_text(Pencil pencil, int wrap, char* fmt, ...)
{
	if(!pencil.sf)
		ui_error(_("Invalid surface."));
	if(!pencil.font)
		ui_error(_("Invalid font."));

	// create print string
	char buffer[1024];
	va_list args;
	va_start(args, fmt);
	vsnprintf(buffer, 1024, fmt, args);
	va_end(args);

	// wrap
	char* lines[100];
	int n_lines = wordwrap(buffer, wrap, lines);
	
	// create text surfaces
	SDL_Surface **texts1 = malloc(sizeof(SDL_Surface*) * n_lines),
	            **texts2 = malloc(sizeof(SDL_Surface*) * n_lines);
	int i = 0, max_w = 0;
	for(i=0; i<n_lines; i++)
	{
		texts1[i] = TTF_RenderUTF8_Solid(pencil.font, lines[i], 
				pencil.color);
		texts2[i] = TTF_RenderUTF8_Solid(pencil.font, lines[i], 
				pencil.shadow);
		if(texts1[i]->w > max_w)
			max_w = texts1[i]->w;
	}

	// create main surface
	SDL_Surface* sf = SDL_CreateRGBSurface(SDL_SWSURFACE, max_w, 
			TTF_FontLineSkip(pencil.font) * n_lines + 1, 8,
			0, 0, 0, 0);
	setup_palette(sf);
	SDL_SetColorKey(sf, SDL_SRCCOLORKEY|SDL_RLEACCEL, TRANSPARENT);
	SDL_FillRect(sf, NULL, TRANSPARENT);

	// paste images
	int y = 0;
	for(i=0; i<n_lines; i++)
	{
		SDL_BlitSurface(texts2[i], NULL, sf, &(SDL_Rect) { 1, y+1 });
		SDL_BlitSurface(texts1[i], NULL, sf, &(SDL_Rect) { 0, y });
		y += TTF_FontLineSkip(pencil.font);
	}

	// cleanup
	for(i=0; i<n_lines; i++)
	{
		SDL_FreeSurface(texts1[i]);
		SDL_FreeSurface(texts2[i]);
	}

	return sf;
}


// Calculate how much width the text will require
int text_width(Pencil pencil, char* fmt, ...)
{
	// create print string
	char buffer[1024];
	va_list args;
	va_start(args, fmt);
	vsnprintf(buffer, 1024, fmt, args);
	va_end(args);

	int w, h;
	int n = TTF_SizeUTF8(pencil.font, buffer, &w, &h);
	if(n == -1)
		ui_error(_("Error getting text width: %s"), TTF_GetError());
	return w;
}
